//
//  Device.cpp
//  RenderV1
//
//  Created by 黄翔 on 2019/9/22.
//  Copyright © 2019 黄翔. All rights reserved.
//

#include "Engine.h"

using namespace hxe;

Engine* Engine::instance = nullptr;

Engine* Engine::createEngine(int width, int height, const char* caption)
{
    if (Engine::instance != nullptr)
    {
        return Engine::instance;
    }
    
    Engine* device = new Engine(width, height, caption);
    Engine::instance = device;
    
    device->input = new Input();
    device->time = new Time();
    device->logger = new Logger();
    device->video = new Video();
    device->scene = new Scene();
    device->hLua = new HLua();
    device->assetDatabase = new AssetDatabase();

    HLuaInst->start();

    return device;
}

Engine * hxe::Engine::getInstance()
{
    return instance;
}


GLFWwindow* hxe::Engine::getWindow() const
{
    return window;
}

hxe::Input* hxe::Engine::getInput() const
{
    return input;
}

hxe::Time* hxe::Engine::getTime() const
{
    return time;
}


Logger* hxe::Engine::getLogger() const
{
    return logger;
}


hxe::Video* hxe::Engine::getVideo() const
{
    return video;
}

hxe::Scene* hxe::Engine::getScene() const
{
    return scene;
}

hxe::HLua* hxe::Engine::getHLua() const
{
    return hLua;
}

hxe::AssetDatabase* hxe::Engine::getAssetDatabase() const
{
    return assetDatabase;
}

hxe::Engine::~Engine()
{
    glfwTerminate();
    HLuaInst->destroy();
    input->drop();
    time->drop();
    logger->drop();
    video->drop();
    scene->drop();
    hLua->drop();
    assetDatabase->drop();
}

bool Engine::run()
{
    if (glfwWindowShouldClose(window))
    {
        return false;
    }

    if (input->getKeyDown(GLFW_KEY_ESCAPE))
    {
        glfwSetWindowShouldClose(window, true);
    }

    time->update();

    return true;
}

Engine::Engine(int width, int height, const char* caption)
{
    width = width;
    height = height;

    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
#endif
    glfwWindowHint(GLFW_SAMPLES, 4);

    window = glfwCreateWindow(width, height, caption, NULL, NULL);
    if (window == NULL)
    {
        return;
    }
    glfwMakeContextCurrent(window);

    glfwSetFramebufferSizeCallback(window, Engine::frameBufferResize);

    glfwSetCursorPosCallback(window, Engine::processMouseInput);

    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);

    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        return;
    }
}

void Engine::processMouseInput(GLFWwindow* window, double xPos, double yPos)
{
    Input* input = Engine::instance->getInput();
    input->mousePosition = Vector2(xPos, yPos);
}

void Engine::frameBufferResize(GLFWwindow* window, int width, int height)
{
    Engine::instance->width = width;
    Engine::instance->height = height;

    glViewport(0, 0, width, height);
}
